import update from 'immutability-helper';
import { message } from 'antd';
import findIndex from 'lodash/findIndex';
import omit from 'lodash/omit';
import {
  getAction,
  getLevel,
  $$set,
  pickLast,
  addRule,
  hasKey,
  dealId,
  resetSpan,
} from '@/pages/FormDesigner/components/utils';
import { query } from '@/pages/FormDesigner/services';

window.resetSpan = resetSpan;
const initState = {
  showHideItem: true,
  current: {},
  formSchema: [],
  linkages: [],
  vertical: true,
  columnNum: 3,
  labelWidth: 0,
  submitUrl: '',
  needBack: false,
};

export default {
  namespace: 'formDesigner',

  state: initState,

  effects: {
    *getInitData({ payload }, { call, put }) {
      const { success, data, errMessage } = yield call(query, payload.formVersionId);

      if (!success) {
        message.error(errMessage);
      } else {
        const {
          formId,
          formVersionId,
          eleDriveRuleList = [],
          elementList = [],
          columnNum = 3,
          labelWidth,
          submitUrl,
          saveUrl,
          vertical,
          needSubmit,
          needSave,
          needBack,
        } = data;
        yield put({
          type: 'update',
          payload: {
            formId,
            formVersionId,
            linkages: eleDriveRuleList,
            formSchema: dealId(elementList),
            columnNum,
            vertical,
            labelWidth,
            submitUrl,
            saveUrl,
            needSubmit,
            needSave,
            needBack,
          },
        });
      }
    },
  },

  reducers: {
    update(state, { payload }) {
      window.arr = payload.formSchema;

      return {
        ...state,
        ...payload,
      };
    },
    setCurrent(state, { payload }) {
      return {
        ...state,
        current: payload,
      };
    },
    // 重置每个formItem的megaProps.span = 1; 同时更新forForm相关的字段
    updateSpan(state, { payload }) {
      const { formSchema } = state;

      return {
        ...state,
        ...payload,
        formSchema: resetSpan(formSchema),
      };
    },
    /**
     * 全量更新
     */
    updateFormSchema(state, { payload }) {
      window.arr = payload;
      return {
        ...state,
        formSchema: payload,
      };
    },
    updateNode(state, { payload }) {
      const { current, formSchema } = state;
      const level = getLevel(formSchema, { __id: current.__id });

      return {
        ...state,
        formSchema: update(
          formSchema,
          getAction(level, { $splice: [[pickLast(level), 1, { ...current, ...payload }]] })
        ),
      };
    },
    /**
     * 修改已存在的节点信息
     * @param {object} payload 包含 index和item，前置表示路径 'formSchema[0].properties[0]' ，后者包含当前组件属性
     */
    updateItem(state, { payload }) {
      const { formSchema, current } = state;
      let raw = {};
      const { rules = [] } = current;
      // 更新rules中的required规则
      if (hasKey(payload, 'required')) {
        raw = {
          ...current,
          rules: addRule(rules, 'required', {
            required: payload.required,
            whitespace: true,
            message: '必填项',
          }),
        };
      } else if (hasKey(payload, 'pattern') || hasKey(payload, 'patternMsg')) {
        // 更新rules中的pattern规则
        const targetIndex = findIndex(rules, item => item.pattern !== undefined);
        let newItem = {};

        if (hasKey(payload, 'patternMsg')) {
          newItem = { message: payload.patternMsg };
        } else {
          newItem = { pattern: payload.pattern };
        }
        if (targetIndex !== -1) {
          newItem = { ...rules[targetIndex], ...newItem };
        }
        raw = {
          ...current,
          rules: addRule(rules, 'pattern', newItem),
        };
      } else if (hasKey(payload, 'format') || hasKey(payload, 'formatMsg')) {
        // 更新rules中的format规则
        const targetIndex = findIndex(rules, item => item.format !== undefined);
        let newItem = {};

        if (hasKey(payload, 'formatMsg')) {
          newItem = { message: payload.formatMsg };
        } else {
          newItem = { format: payload.format };
        }

        if (targetIndex !== -1) {
          newItem = { ...rules[targetIndex], ...newItem };
        }
        raw = {
          ...current,
          rules: addRule(rules, 'format', omit(newItem, ['pattern'])),
        };
      } else {
        raw = { ...current, ...payload };
      }
      window.arr = $$set(formSchema, raw.level, omit(raw, ['level']));
      // BUG: 不能根据current.level查找节点数据，因为在拖拽排序的时候level是变化的
      return {
        ...state,
        current: raw,
        formSchema: $$set(formSchema, raw.level, omit(raw, ['level'])),
      };
    },
    removeRule(state, { payload }) {
      const { formSchema, current } = state;
      const { ruleName } = payload;
      let raw = {};
      const { rules = [] } = current;
      const targetIndex = findIndex(rules, item => item[ruleName] !== undefined);

      if (targetIndex === -1) {
        return state;
      }
      raw = {
        ...current,
        rules: update(rules, { $splice: [[targetIndex, 1]] }),
      };

      return {
        ...state,
        current: raw,
        formSchema: $$set(formSchema, current.level, raw),
      };
    },
    clear() {
      return initState;
    },
    removeItem(state, { payload }) {
      const { formSchema } = state;
      const { level } = payload;

      return {
        ...state,
        formSchema: update(formSchema, getAction(level, { $splice: [[pickLast(level), 1]] })),
        current: {},
      };
    },
  },
};
